package com.yc.shadowdemo.plugin

import android.app.ActivityManager
import android.app.Application
import android.content.Context
import android.os.Build
import android.os.Process
import android.os.StrictMode
import android.os.StrictMode.VmPolicy
import android.util.Log
import android.webkit.WebView
import com.tencent.shadow.core.common.LoggerFactory
import com.tencent.shadow.dynamic.host.DynamicPluginManager
import com.tencent.shadow.dynamic.host.DynamicRuntime
import java.io.File
import java.util.concurrent.Future

/**
 * Creator: yc
 * Date: 2021/5/19 15:37
 * UseDes:插件初始化
 */
public class YcPluginInit {
    companion object {
        const val PLUGIN_PROCESS_NAME: String = ":plugin"
        val mInstance: YcPluginInit = YcPluginInit()
        fun isProcess(context: Context, processName: String): Boolean {
            var currentProcName = ""
            val manager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
            for (processInfo in manager.runningAppProcesses) {
                if (processInfo.pid == Process.myPid()) {
                    currentProcName = processInfo.processName
                    break
                }
            }
            return currentProcName.endsWith(processName)
        }
    }

    /**
     * 这个PluginManager对象在Manager升级前后是不变的。它内部持有具体实现，升级时更换具体实现。
     */
    lateinit var mPluginManager: DynamicPluginManager

    /**
     *
     * @param pluginManagerApkPath String   管理器apk文件路径
     */
    fun init(application: Application, pluginManagerApkPath: String) {
//        detectNonSdkApiUsageOnAndroidP()
//        setWebViewDataDirectorySuffix()
        //Log接口Manager也需要使用，所以主进程也初始化。
        LoggerFactory.setILoggerFactory(YcPluginLoggerFactory.getInstance())
        //"plugin"需与AndroidManifest.xml里注册的YcMainPluginProcessService服务的android:process=":plugin"里一致
        if (isProcess(application, PLUGIN_PROCESS_NAME)) {
            //在全动态架构中，Activity组件没有打包在宿主而是位于被动态加载的runtime，
            //为了防止插件crash后，系统自动恢复crash前的Activity组件，此时由于没有加载runtime而发生classNotFound异常，导致二次crash
            //因此这里恢复加载上一次的runtime
            DynamicRuntime.recoveryRuntime(application)
        }
        val fixedPathPmUpdater = YcFixedPathPmUpdater(File(pluginManagerApkPath))
        //之前正在更新中，暗示更新出错了，应该放弃之前的缓存  或者 没有本地缓存
        if (fixedPathPmUpdater.wasUpdating() || fixedPathPmUpdater.latest == null) {
            try {
                val update: Future<File> = fixedPathPmUpdater.update()
                update.get() //这里是阻塞的，需要业务自行保证更新Manager足够快。
            } catch (e: Exception) {
                throw RuntimeException("host更新Manager出错!!", e)
            }
        }
        mPluginManager = DynamicPluginManager(fixedPathPmUpdater)
    }

    private fun setWebViewDataDirectorySuffix() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
            return
        }
        WebView.setDataDirectorySuffix(Application.getProcessName())
    }

    private fun detectNonSdkApiUsageOnAndroidP() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
            return
        }
        val builder = VmPolicy.Builder()
        builder.detectNonSdkApiUsage()
        StrictMode.setVmPolicy(builder.build())
    }

}